﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System;
using System.Xml.Serialization;
using System.Collections.Specialized;
using System.Runtime.Serialization;
using System.Threading;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using BrainTechLLC.ThreadSafeObjects;
using WordsMatching;
#if USE_HYPER
using Hyper.ComponentModel;
#endif

namespace BrainTechLLC
{
    [Flags]
    [DataContract]
    public enum HasDataIndex : byte
    {
        [EnumMember]
        None = 0,
        [EnumMember]
        I1 = 1,
        [EnumMember]
        I2 = 2,
        [EnumMember]
        I3 = 4,
        [EnumMember]
        I4 = 8,
        [EnumMember]
        I5 = 16,
        [EnumMember]
        I6 = 32,
        [EnumMember]
        I7 = 64,
        [EnumMember]
        I8 = 128
    }

    [DataContract]
    [Serializable]
    public class LocationEdgeData
    {
        public int x, y, z;
        public byte d;
        public float m;
        public long id;
    }

#if NO_SILVERLIGHT
    [Browsable(true)]
    [TypeConverter(typeof(ExpandableObjectConverter))]
    [EditorBrowsable(EditorBrowsableState.Always)]
#endif
    [DataContract]
    [Serializable]
    public class LocationEdge : BaseClass, IGameThing, IHasPropertyData, INotifyPropertyChanged, INotifyPropertyChanging, INotifyCollectionChanged, IAssociatedID
    {
        [DataMember]
        public GeneralDirection _direction;

        [DataMember]
        public long _toLocationId;

        [DataMember]
        public float _baseMoveCost;

        [DataMember]
        public long _edgeDataID;

        public long EdgeDataID
        {
            get { return _edgeDataID; }
            set
            {
                if (!_edgeDataID.AreEqual(value))
                {
                    OnPropertyChanging("EdgeDataID", _edgeDataID, value);
                    _edgeDataID = value;
                    OnPropertyChanged("EdgeDataID", _edgeDataID, value);
                }
            }
        }

        public EdgeData EdgeData
        {
            get
            {
                if (_edgeDataID == 0)
                    return null;

                return Everything.Find<EdgeData>(EdgeDataID);
            }
            set
            {
                if (value == null || _edgeDataID != value.AssociatedID)
                {
                    if (value == null)
                        EdgeDataID = 0;
                    else
                        EdgeDataID = value.AssociatedID;
                }
            }
        }

        [DataMember]
        public int _vnum;

        public int Vnum
        {
            get { return _vnum; }
            set
            {
                if (!_vnum.AreEqual(value))
                {
                    OnPropertyChanging("Vnum", _vnum, value);
                    _vnum = value;
                    OnPropertyChanged("Vnum", _vnum, value);
                };
            }
        }


        public bool HasEdgeData
        {
            get
            {
                if (_edgeDataID == 0)
                    return false;

                return true;
            }
        }

#if NO_SILVERLIGHT
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        public GeneralDirection Direction
        {
            get { return _direction; }
            set
            {
                if (!_direction.AreEqual(value))
                {
                    OnPropertyChanging("Direction", _direction, value);
                    _direction = value;
                    OnPropertyChanged("Direction", _direction, value);
                }
            }
        }

        public LocationEdge GetIncomingEdgeForOutgoingDirection(GeneralDirection dir)
        {
            GameLocation loc = ToGameLocation;

            if (loc == null)
                return null;

            GeneralDirection oppDir = dir.ReverseDirection();

            return loc.Edges[(int)oppDir];
        }

#if NO_SILVERLIGHT
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        public long ToLocationId
        {
            get { return _toLocationId; }
            set
            {
                if (!_toLocationId.AreEqual(value))
                {
                    OnPropertyChanging("ToLocationId", _toLocationId, value);
                    _toLocationId = value;
                    OnPropertyChanged("ToLocationId", _toLocationId, value);
                }
            }
        }

#if NO_SILVERLIGHT
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        public float BaseMoveCost
        {
            get { return _baseMoveCost; }
            set
            {
                if (!_baseMoveCost.AreEqual(value))
                {
                    OnPropertyChanging("BaseMoveCost", _baseMoveCost, value);
                    _baseMoveCost = value;
                    OnPropertyChanged("BaseMoveCost", _baseMoveCost, value);
                }
            }
        }

        public long ToGameLocationID
        {
            get
            {
                var loc = ToGameLocation;
                return (loc == null) ? 0 : loc.AssociatedID;
            }
        }

#if NO_SILVERLIGHT
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlIgnore]
        public GameLocation ToGameLocation
        {
            get
            {
                if (_toLocationId == 0)
                    return null;

                return _toLocationId.Find<GameLocation>();
            }
            set
            {
                if (value == null)
                    ToLocationId = 0;

                ToLocationId = value.AssociatedID;
            }
        }

        public override void RegisterChildrenForPropertyChangeEvents()
        {            
            base.RegisterChildrenForPropertyChangeEvents();
        }        
    }
}